#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
基础Side-Channel AttackExample
演示如何Use基础AttackModule进行CPA、DPA、SPAAndTemplate Attack
"""

import os
import sys
from pathlib import Path

# Add父DirectoryToPath
sys.path.insert(0, str(Path(__file__).parent.parent))

from cpa_attack import CPAAttack
from dpa_attack import DPAAttack
from spa_attack import SPAAttack
from template_attack import TemplateAttack


def run_basic_attack_example():
    """Run基础AttackExample"""
    
    # SettingsTestDataPath
    test_data_dir = Path(__file__).parent.parent / "power_traces"
    aes_traces = test_data_dir / "aes_test_traces.npz"
    
    if not aes_traces.exists():
        print(f"[FAIL] TestDataNot存In: {aes_traces}")
        print("请先Run以下CommandGenerateTestData:")
        print("cd /home/ga4ss/workspace/j0ker/xchip")
        print("python3 tools/power_trace_generator.py -a aes -n 50 -o side_channel_attacks/power_traces/aes_test_traces.npz --noise")
        return
    
    print("=" * 60)
    print("基础Side-Channel AttackExample")
    print("=" * 60)
    print(f"UseTestData: {aes_traces}")
    
    # LoadData获取True实Key
    import numpy as np
    data = np.load(aes_traces, allow_pickle=True)
    true_key = data['keys'][0]  # 获取First个Key作For目标
    true_key_byte = true_key[0] if isinstance(true_key, (bytes, np.ndarray)) else true_key
    print(f"目标Key字节 0: 0x{true_key_byte:02x}")
    print()
    
    # 1. CPAAttackExample
    print("[Target] 1. CPA (相关Power Analysis) Attack")
    print("-" * 40)
    
    cpa = CPAAttack()
    if cpa.load_data(str(aes_traces)):
        print("[OK] CPAAttackDataLoadSuccess")
        
        # RunCPAAttack
        result = cpa.attack(target_byte=0)
        
        print(f"AttackResult:")
        print(f"  - Success: {result.success}")
        print(f"  - 置信度: {result.confidence:.4f}")
        print(f"  - 最佳False设: 0x{result.best_hypothesis:02x}")
        print(f"  - True实Key: 0x{true_key_byte:02x}")
        print(f"  - Execute时间: {result.execution_time:.2f}秒")
        
        # CheckAttackYesNo正确
        attack_correct = result.best_hypothesis == true_key_byte
        if result.success and attack_correct:
            print("[Success] CPAAttackSuccess且Key正确!")
        elif result.success and not attack_correct:
            print("[WARNING] CPAAttackSuccess但KeyError!")
        else:
            print("[FAIL] CPAAttack未达ToSuccess阈值")
    else:
        print("[FAIL] CPAAttackDataLoadFailed")
    
    print()
    
    # 2. DPAAttackExample
    print("[Target] 2. DPA (差分Power Analysis) Attack")
    print("-" * 40)
    
    dpa = DPAAttack()
    if dpa.load_data(str(aes_traces)):
        print("[OK] DPAAttackDataLoadSuccess")
        
        # RunDPAAttack
        result = dpa.attack(target_byte=0)
        
        print(f"AttackResult:")
        print(f"  - Success: {result.success}")
        print(f"  - 置信度: {result.confidence:.4f}")
        print(f"  - 最佳False设: 0x{result.best_hypothesis:02x}")
        print(f"  - True实Key: 0x{true_key_byte:02x}")
        print(f"  - Execute时间: {result.execution_time:.2f}秒")
        
        # CheckAttackYesNo正确
        attack_correct = result.best_hypothesis == true_key_byte
        if result.success and attack_correct:
            print("[Success] DPAAttackSuccess且Key正确!")
        elif result.success and not attack_correct:
            print("[WARNING] DPAAttackSuccess但KeyError!")
        else:
            print("[FAIL] DPAAttack未达ToSuccess阈值")
    else:
        print("[FAIL] DPAAttackDataLoadFailed")
    
    print()
    
    # 3. SPAAttackExample
    print("[Target] 3. SPA (SimplePower Analysis) Attack")
    print("-" * 40)
    
    spa = SPAAttack()
    if spa.load_data(str(aes_traces)):
        print("[OK] SPAAttackDataLoadSuccess")
        
        # RunSPAAttack
        result = spa.attack(target_byte=0)
        
        print(f"AttackResult:")
        print(f"  - Success: {result.success}")
        print(f"  - 置信度: {result.confidence:.4f}")
        print(f"  - Execute时间: {result.execution_time:.2f}秒")
        
        if result.success:
            print("[Success] SPAAttackSuccess!")
        else:
            print("[WARNING] SPAAttack未达ToSuccess阈值")
    else:
        print("[FAIL] SPAAttackDataLoadFailed")
    
    print()
    
    # 4. Template AttackExample
    print("[Target] 4. Template (模板) Attack")
    print("-" * 40)
    
    template = TemplateAttack()
    if template.load_data(str(aes_traces)):
        print("[OK] Template AttackDataLoadSuccess")
        
        # RunTemplate Attack
        result = template.attack(target_byte=0)
        
        print(f"AttackResult:")
        print(f"  - Success: {result.success}")
        print(f"  - 置信度: {result.confidence:.4f}")
        print(f"  - Execute时间: {result.execution_time:.2f}秒")
        
        if result.success:
            print("[Success] Template AttackSuccess!")
        else:
            print("[WARNING] Template Attack未达ToSuccess阈值")
    else:
        print("[FAIL] Template AttackDataLoadFailed")
    
    print()
    print("=" * 60)
    print("基础AttackExampleCompleted")
    print("=" * 60)


def demonstrate_attack_parameters():
    """演示AttackParameters的影响"""
    
    test_data_dir = Path(__file__).parent.parent / "power_traces"
    aes_traces = test_data_dir / "aes_test_traces.npz"
    
    if not aes_traces.exists():
        print("[FAIL] TestDataNot存In，SkipParameters演示")
        return
    
    print("\n[Test] AttackParameters影响演示")
    print("-" * 40)
    
    cpa = CPAAttack()
    cpa.load_data(str(aes_traces))
    
    # TestNot同目标字节
    print("TestNot同目标字节的Attack效果:")
    for target_byte in [0, 1, 2]:
        try:
            result = cpa.attack(target_byte=target_byte)
            print(f"  字节 {target_byte}: 置信度 {result.confidence:.4f}, Success: {result.success}")
        except Exception as e:
            print(f"  字节 {target_byte}: AttackFailed - {e}")
    
    print()


def compare_attack_methods():
    """CompareNot同AttackMethod的效果"""
    
    test_data_dir = Path(__file__).parent.parent / "power_traces"
    aes_traces = test_data_dir / "aes_test_traces.npz"
    
    if not aes_traces.exists():
        print("[FAIL] TestDataNot存In，SkipMethodCompare")
        return
    
    print("\n[Stats] AttackMethodCompare")
    print("-" * 40)
    
    # 获取True实Key
    import numpy as np
    data = np.load(aes_traces, allow_pickle=True)
    true_key = data['keys'][0]
    true_key_byte = true_key[0] if isinstance(true_key, (bytes, np.ndarray)) else true_key
    
    attacks = {
        'CPA': CPAAttack(),
        'DPA': DPAAttack(),
        'SPA': SPAAttack(),
        'Template': TemplateAttack()
    }
    
    results = {}
    
    for name, attack in attacks.items():
        try:
            attack.load_data(str(aes_traces))
            result = attack.attack(target_byte=0)
            
            # CheckKeyYesNo正确（IfHasbest_hypothesis）
            key_correct = False
            if hasattr(result, 'best_hypothesis') and result.best_hypothesis is not None:
                key_correct = result.best_hypothesis == true_key_byte
            
            results[name] = {
                'success': result.success,
                'confidence': result.confidence,
                'time': result.execution_time,
                'key_correct': key_correct,
                'best_hypothesis': getattr(result, 'best_hypothesis', None)
            }
        except Exception as e:
            results[name] = {'error': str(e)}
    
    # OutputCompareResult
    print(f"True实Key字节 0: 0x{true_key_byte:02x}")
    print(f"{'Method':<10} {'Success':<6} {'置信度':<8} {'时间(秒)':<10} {'Key正确':<8}")
    print("-" * 50)
    
    for name, result in results.items():
        if 'error' in result:
            print(f"{name:<10} {'Error':<6} {'-':<8} {'-':<10} {'-':<8}")
        else:
            success_str = "[OK]" if result['success'] else "[FAIL]"
            key_str = "[OK]" if result['key_correct'] else "[FAIL]" if result['best_hypothesis'] is not None else "-"
            print(f"{name:<10} {success_str:<6} {result['confidence']:<8.4f} {result['time']:<10.2f} {key_str:<8}")
    
    # 找出最佳Method
    successful_attacks = [(name, r) for name, r in results.items() 
                         if 'error' not in r and r['success']]
    
    if successful_attacks:
        best_attack = max(successful_attacks, key=lambda x: x[1]['confidence'])
        print(f"\n[Best] 最佳AttackMethod: {best_attack[0]} (置信度: {best_attack[1]['confidence']:.4f})")
    else:
        print("\n[WARNING] 没HasAttackMethodSuccess")


if __name__ == "__main__":
    try:
        run_basic_attack_example()
        demonstrate_attack_parameters()
        compare_attack_methods()
        
    except KeyboardInterrupt:
        print("\n[WARNING] 用户Interrupt操作")
    except Exception as e:
        print(f"\n[FAIL] ExampleRunFailed: {e}")
        sys.exit(1)
